package com.qq.集合.Stream流;

import java.util.*;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

//Stream流的收集操作
//收集Stream流的含义：就是把Stream流中间操作后的结果数据转回到集合或者数组中去。

//Stream流：方便操作集合/数组的手段。
//集合/数组：才是开发中的目的。

//Stream流的方法：
//collect​(Collector collector)				开始收集Stream流，指定收集器
//Collectors的静态方法：
//public static <T> Collector toList​()		把元素收集到List集合中
//public static <T> Collector toSet​()		把元素收集到Set集合中
//public static  Collector toMap​(Function keyMapper , Function valueMapper)	把元素收集到Map集合中

public class Stream_Test3 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");
        
        //1.转List集合————遍历流，将元素收集到创建好的List集合，然后返回
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        List<String> zhangList = s1.collect(Collectors.toList()); // 可变集合
        zhangList.add("java1");
        System.out.println(zhangList);

//       List<String> list1 = s1.toList(); // 把流收集为不可变集合 ，1.9才能用
//       list1.add("java");//报错
//       System.out.println(list1);
        
        //2.转set集合
        Stream<String> s2 = list.stream().filter(s -> s.startsWith("张"));
        Set<String> zhangSet = s2.collect(Collectors.toSet());//重复就不存
        System.out.println(zhangSet);
        
        //3.转数组
        Stream<String> s3 = list.stream().filter(s -> s.startsWith("张"));
//      Object[] arrs = s3.toArray(); //因为有办法将其他类型加入到String类型的流，为了严谨，系统用Object数组接收
//      要使用指定类型数组接收，需要创建匿名内部类对象
//      toArray会将流的元素个数传给方法apply，然后返回相同元素个数String类型数组
//        String[] arrs = s3.toArray(new IntFunction<String[]>() {
//        	@Override
//        	public String[] apply(int len) {
//        		return new String[len];
//        	}
//		});    		
        String[] arrs = s3.toArray( len -> new String[len]);
//        String[] arrs = s3.toArray(String[]::new);构造器引用
        System.out.println("Arrays数组内容：" + Arrays.toString(arrs));
        
       
        //4.转map集合
        //1.流转map集合要先去重复，map不能像set一样自动去重，有重复元素不去重会报错,
        //如果一开始是从Map集合获取的键流或键值对流，就不需要用distinct，因为键流何键值对流本身就不重复
        
        //2.流转map集合，会遍历流，然后把一个流元素分别加工（map）成键和值，再存入map集合，全部存入后再返回map集合
         //实际上就是两个加工方法（map），分别返回键 和 值
        
//      两个参数是加工方法的Function匿名内部类对象：
//      toMap(Function k , Function v);
        
//      加工方法：
//      list.stream().map(new Function<String, Student>() {
//    	public Student apply(String t) {
//    		随意操作，返回回去的才是最终数据
//    		return new Student(t);//返回加工后的结果，放到流里
//    	};	
//	});
        
        //map集合获取流
        Map<String,Integer>m = new HashMap<>();
        m.put("赵伟强",22);
        m.put("何金娣",24);
        
        //键流转为map集合	
        Stream<String>s4 = m.keySet().stream();//键流	   //键            //值
        Map<String,Integer>m2 =s4.collect(Collectors.toMap(s -> s , s -> m.get(s)));
        System.out.println(m2);
        //键值对流转为map集合	
        Stream<Map.Entry<String, Integer>>s44 =m.entrySet().stream();//键值对流	
        Map<String,Integer>m3 =s44.collect(Collectors.toMap(s -> s.getKey() ,s -> s.getValue()));   
         
        //list集合获取流
        Stream<String> s5 = list.stream().filter(s -> s.startsWith("张"));
        //List流转map集————要用distinct去重复不然报错
         Map<String,Integer>m1 =s5.distinct().collect(Collectors.toMap(s -> s + "(键)", s -> s.length()) );

         System.out.println(m1);
         System.out.println(m2);
         System.out.println(m3);
        
    }
}
